home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
bit
/
src
/
iopen.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
13KB
|
541 lines
/*
* $Id: iopen.c,v 0.91 1994/02/20 00:53:07 zhao Pre-Release $
*
*. This file is part of BIT shareware package. After the two weeks of
* free evaluation period, you are encouraged (required) to register
* your copy for a small registration fee, which is $35 for personal use
* and $50 for commercial, government and institutional use.
*
* Copyright(c) 1993, 1994 by T.C. Zhao.
* All rights reserved.
*
* Permission to use, copy, and distribute this software in its entirety
* for non-commercial purposes is hereby granted, provided that the
* above shareware and copyright notices and this permission notice
* appear in all copies and their documentation.
*
* This software may be modified for your own use, but modified versions
* may not be distributed without prior consent of the author.
*
* This software is provided "as is" without expressed or implied
* warranty of any kind.
*
*.
*
* Purpose:
* Performs all image IOs.
*
* The opening routine reads MAXSIGL bytes from the image file
* and then walks down the global identification table for matches
* with all signatures if they exist and in case they don't, filename
* extension will be used to guess the image format. In case of multiple
* or conflicting matches, the driver will try to get the image
* description (width, height etc) and only the succesful ones will
* be used.
*/
#if !defined(lint) && defined(F_ID)
char *id_open = "$Id: iopen.c,v 0.91 1994/02/20 00:53:07 zhao Pre-Release $";
#endif
#include "bit.h"
#include "extern.h"
/************************************************************************
* close an image stream.
************************************************************************/
void
close_image(IPTR im)
{
int status = 0;
if (im && im->fp)
{
status = fclose(im->fp);
im->fp = 0;
}
#ifdef MDEBUG
if (status == EOF)
{
M_debug("CloseImage", "Bad close");
}
#endif
}
#define MAXCSIG 4 /* max. conflicting signatures */
/***********************************************************************
* check if an image is in a recognized format. Return index into the
* global image structure. Multiple matches are permitted and the
* description routine will try every one of them until a description
* can be found or all matches are exhausted and in that case, the
* routine returns an error code (-1).
***********************************************************************/
static int no_bark; /* if complain if unknow image type */
int
check_signature(FILE * fp, int found[], const char *fn)
{
unsigned char signature[MAXSIGL + 1];
int i, cfound, j;
const IMG_IO *io;
const char *tmp;
const SIG *s;
if (Badfread(signature, 1, MAXSIGL, fp))
{
if (!no_bark)
Bark("ImageLoad", "%s", feof(fp) ? "Premature EOF" :
"Bad read");
fclose(fp);
return -1;
}
for (i = cfound = 0, io = img_io; i < totalfmt; i++, io++)
{
s = io->sig;
for (j = 0; j < MAXISIG; j++, s++)
{
if (s->len > 0)
{
if (memcmp(s->sig, signature, s->len) == 0)
found[cfound++] = i;
}
else if (j == 0)
{
/*
* no signature, check extensions. Do this only for
* formats that truly do not have a signature, j==0.
*/
if ((tmp = file_ext(fn)) != 0)
if (memcmp(io->ext, tmp, strlen(io->ext)) == 0)
found[cfound++] = i;
}
}
}
return cfound;
}
/*****************************************************************
* Check is the given file, fn, is an image file we can view.
* Will not produce warning messages of any kind.
****************************************************************/
const char *
is_image_file(const char *fn)
{
int cfound = 0, found[MAXCSIG];
FILE *fp;
const char *key = 0;
no_bark = 1; /* shut up complaining */
if ((fp = fn ? fopen(fn, "r") : 0))
{
cfound = check_signature(fp, found, fn);
fclose(fp);
}
/* check if loadable */
if (cfound > 0)
{
if (img_io[found[0]].load != 0)
key = img_io[found[0]].key;
}
no_bark = 0;
return key;
}
/*******************************************************************
* Use the info check_image returned, img_desc tries to get the
* description of the image, width, height, type, among others,
* and fill the related field in image struct
*******************************************************************/
static int
image_desc(IPTR im, int found[], int nf)
{
int i, ok;
IMG_IO *io;
long offset;
if (!im || nf <= 0)
return -1;
/*
* remembner where we are, note that we are not necessarily at the
* begining of the file
*/
offset = ftell(im->fp);
/*
* loop thru all matched signatures and terminate either a description is
* found or all signatures are exhaused
*/
for (i = ok = 0; !ok && i < nf; i++)
{
fseek(im->fp, offset, SEEK_SET);
io = img_io + found[i];
/* get some vital info about the image. */
im->io = io;
im->type = io->type;
im->t2b = io->t2b;
/* if no display function is defined, use the generic one */
if (!io->display)
im->io->display = Generic_display;
/* get image description per instruction */
im->key = im->io->key;
im->info = im->io->info;
ok = io->desc(im) == 0;
}
return ok;
}
/***************************************************************
* Gloabl entry to get an image description from a stream.
* Can't assume that we are at the begining of the file.
* fn is for reporting purpose only.
***************************************************************/
IPTR
open_image_fp(FILE * fp, const char *fn)
{
int cfound, found[MAXCSIG];
IPTR im = 0;
long offset;
/*
* remember where we are. Before handing over the stream for description,
* we must be at the same location within the file
*/
offset = ftell(fp);
if ((cfound = check_signature(fp, found, fn)) <= 0)
{
if (!no_bark)
Bark("OpenImage", "%s -- Unknown image type", fn);
fclose(fp);
return 0;
}
if (!im)
{ /* get_mem_iptr never returns if failure */
im = get_mem_imgptr();
im->cmap = get_mem_cmap();
}
im->fp = fp;
/* restore the position */
if (fseek(im->fp, offset, SEEK_SET))
{
M_err("OpenImage", "Error seeking");
}
Strncpy(im->ifile, fn, TC_FL);
if (image_desc(im, found, cfound) <= 0)
{
/*
* unable to get description. If the format is writeonly, don't
* bitch
*/
if (im->io->load && !no_bark)
{
Bark("ImageOpen", "%s: Error getting %s info",
fn, im->io->key);
}
close_image(im);
free_image(im);
im = 0;
return 0;
}
return im;
}
/*************************************************************************
* Do the same thing, but with a file
*************************************************************************/
IPTR
open_image(const char *fn)
{
FILE *fp;
#ifdef MDEBUG
M_debug("ImgOpen", "Trying_%s_", fn);
#endif
return (fp = msg_fopen(fn, "r")) ? open_image_fp(fp, fn) : 0;
}
/*******************************************************************
* Global entry to load an image.
*
* This routine does it all: given a filename, load_image will
* fill every member of the image structure and return the image
* structure. Bad load is detected by either null return or a zero
* in the ok field of the structure
*******************************************************************/
IPTR
load_image_fp(FILE * fp, const char *fn)
{
IPTR im = open_image_fp(fp, fn);
int scans, err = 0;
pc_t lut[PCMAX];
if (!im || img_get_rastermem(im) < 0)
{
close_image(im);
free_image(im);
return 0;
}
/* in case fit_image_size is active */
open_main_window(im);
update_image_info(im);
im->ok = (scans = im->io->load(im)) >= 0;
if (!im->ok) /* can't load the darn thing */
{
close_image(im);
free_image(im);
end_busy();
return 0;
}
if (scans != 0 && (im->h != scans))
{
err = 1;
/* bitch only if more than one line bad */
if ((im->h - scans) > 1)
Bark("ImageLoad", "%s: Only gotten %d of %d lines",
im->ifile, scans, im->h);
}
if (im->io->textsgf) /* load text only if image ok */
{
M_info("ImgOpen", "Trying sgfs and text", fn);
load_text(im);
load_sgf(im);
}
end_busy();
/* close image only if there is no more */
if (!im->more)
close_image(im);
if (im->t2b) /* convert scan so that it runs from bottom
* to top */
{
M_info("ImgOpen", "flipping");
(void) flip_mat(im->mraster, im->h, im->w, 'r', im->esize);
im->t2b = 0;
}
/*
* to minimize interferance with window manager, we swap colormaps
* entries to force some of the colors to be static, i.e., having the
* same index as the default system map
*/
if (IS_CI(im))
{
/*
* if an error occured, we must mask off bits higher than CMAPBITS
* because some of the pixel may have random values. A possible
* optimization here is to mask only the scan lines that are bad.
* Another possibility is to use calloc throughout
*/
M_info("ImgOpen", "Preserving");
if (err)
do_ci_mask(im->raster, im->h * im->w, im->cmap->colors - 1);
if (preserve_wm_colors)
img_preserve_wm_colors(im);
/* find out the number of unique colors */
cmap_ucolors(im->cmap, lut);
}
/* check for aspect ratio and correct it if need to */
if (im->aspect != 1000 && im->aspect != 0)
{
int nw, nh;
if (yes_no("Display", "Non-square pixel", "Correct ?", 0))
{
if (im->aspect > 1000)
{
nw = (im->w * im->aspect) / 1000;
nh = im->h;
}
else
{
nh = (im->h * 1000) / im->aspect;
nw = im->w;
}
img_scale(im, nh, nw, 1, 0, 0);
}
im->aspect = 1000;
}
M_info("ImgOpen", "Load %s",
im && im->io && im->io->display ? "OK" : "Not Ok");
return im;
}
IPTR
load_image(const char *fn)
{
FILE *fp;
return (fp = msg_fopen(fn, "r")) ? load_image_fp(fp, fn) : 0;
}
/******************************************************************
* Write the image to disk using the function io->dump.
*****************************************************************/
int
write_image(const IMG_IO * io, IPTR im, const char *fn)
{
int err = 0, swap = 0;
ci_t tran[2];
if (!(im->fp = msg_fopen(fn, "w")))
return -1;
/*
* Due to wm_color preservation, B&W might've been swapped. Take care of
* the swap: 1's are supposed to be black
*/
if (IS_BW(im))
{
if ((swap = im->cmap->ct[0][0] == 0))
{
tran[0] = 1;
tran[1] = 0;
modify_all_ci(im->raster, im->w * im->h, tran);
}
}
/*
* check raster direction. No need to do this as the writing routine
* always knows the raster is handed with (0,0) at lower-left corner
*/
#if 0
if (io->t2b != im->t2b)
{
set_matop_quiet(1);
flip_matrix(im->mraster, im->h, im->w, 'r', im->esize);
im->t2b = !im->t2b;
}
#endif
/* if cmap, see if we can squeeze the image size */
if (io->type == im->type && IS_CI(im))
{
squeeze_image(im);
}
/* final check to make sure everything is ok, quantize if necessary */
if (io->type != im->type)
{
if (io->type == T_CMAP) /* need special handling */
{
err = io->ncols;
set_quant_max_color(err <= 0 ? MAXCML : err);
}
err = img_convert_type(im, io->type);
}
if (!err && (err = io->dump(im) < 0))
{
Bark("WriteImage", "%s: Error writing", fn);
}
/*
* write text and marking info only if the current format is capable of
* handling it
*/
if (!err && io->textsgf)
{
dump_text(im->fp);
dump_sgf(im->fp);
}
close_image(im);
/* swap again for correct display */
if (swap)
modify_all_ci(im->raster, im->w * im->h, tran);
return err;
}
/******************************************************************
* Handle multi-images
*****************************************************************/
int
handle_multi_images(IPTR im)
{
int n = 0;
do
{
im->io->inext(im, ++n);
if (im->ok)
{
im->io->display(im, 0, 0);
}
}
while (im->more);
/* must close the image stream here */
close_image(im);
return 0;
}
/* utility function for fopen, print a message if failure */
FILE *
msg_fopen(const char *ofile, const char *mode)
{
FILE *fp = 0;
if (!ofile || !*ofile)
{
Bark("Fopen", "Bad filname");
return 0;
}
if (!(fp = fopen(ofile, mode)))
Bark("Fopen", ofile);
return fp;
}